package weaver.aiyh_pcn.fadada.util;

import aiyh.utils.Util;
import aiyh.utils.entity.ApiConfigMainDTO;
import aiyh.utils.httpUtil.ResponeVo;
import aiyh.utils.mapUtil.ParaMap;
import aiyh.utils.sqlUtil.sqlResult.impl.PrepSqlResultImpl;
import aiyh.utils.zwl.common.ToolUtil;
import com.alibaba.fastjson.JSON;
import com.api.aiyh_pcn.fadada.dao.FaDDContractMapping;
import com.api.aiyh_pcn.fadada.entity.FaDaDaConfigDTO;
import com.api.aiyh_pcn.fadada.service.impl.FaDDContractService;
import com.api.aiyh_pcn.fadada.util.FaDDRequestUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.weaver.general.TimeUtil;
import org.h2.util.StringUtils;
import weaver.aiyh_pcn.fadada.entity.FileInfo;
import weaver.conn.RecordSet;
import weaver.file.ImageFileManager;
import weaver.formmode.data.ModeDataIdUpdate;
import weaver.formmode.setup.ModeRightInfo;
import weaver.hrm.User;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author EBU7-dev1-ayh
 * @create 2021/11/3 0003 16:50
 * heton gonjvlei
 */


public class FaddContractUtil {
    private String workflowId;
    private String requestId;
    private String mainTableName;
    private String tableName;
    private String customerNo;
    private String contractField;
    private String queueSigned;
    private final String contractInfoTable = "uf_contract_info";
    private String customerNoField;
    private List<Map<String, Object>> detailMaps;
    private Map<String, Object> mainMap;
    private FaDDContractMapping faDDContractMapping = new FaDDContractMapping();
    private FaDDContractService faDDContractService = new FaDDContractService();
    private final ToolUtil toolUtil = new ToolUtil();
    private User user;

    public FaddContractUtil() {
    }

    public FaddContractUtil(String workflowId, String requestId, String mainTableName, String tableName, String customerNo,
                            String customerNoField, String contractField, String queueSigned, List<Map<String, Object>> detailMaps, Map<String, Object> mainMap,
                            User user) {
        this.workflowId = workflowId;
        this.requestId = requestId;
        this.mainTableName = mainTableName;
        this.tableName = tableName;
        this.customerNo = customerNo;
        this.customerNoField = customerNoField;
        this.contractField = contractField;
        this.queueSigned = queueSigned;
        this.detailMaps = detailMaps;
        this.mainMap = mainMap;
        this.user = user;
    }

    /**
     * 创建合同
     */
    public void createContract(Map<String, Object> mainMap) {
//		查询配置参数
        FaDaDaConfigDTO faDaDaConfigDTO = faDDContractMapping.queryConfig(workflowId, 2);
//		查询api配置参数
        ApiConfigMainDTO apiConfigMainDTO = Util.queryApiConfig(Util.null2String(faDaDaConfigDTO.getParamsConfig()));
        RecordSet rs = new RecordSet();
        List<FileInfo> fileInfos = this.contractHandle(this.contractField);
        List<String> contractNoIds = new ArrayList<>();
        List<String> fileNoIds = new ArrayList<>();
        List<String> fileName = new ArrayList<>();
        if (fileInfos.size() == 0) {
            toolUtil.writeErrorLog("fileInfos 为空");
        }
//		多文件的时候会遍历文件去创建合同问文件，但是一个流程只创建一次，一次可能回有多份文件需要创建为合同文件
        for (FileInfo fileInfo : fileInfos) {
//				发起合同创建
            ResponeVo contract = FaDDRequestUtils.createContract(fileInfo, apiConfigMainDTO.getApiUrl());
            Map<String, Object> result;
            try {
                Map<String, Object> entityMap = contract.getEntityMap();
                if (!"200".equals(String.valueOf(entityMap.get("code")))) {
                    toolUtil.writeErrorLog("创建合同失败，错误信息:" + entityMap.get("message"));
                    throw new RuntimeException("创建合同失败！");
                }
                result = (Map<String, Object>) entityMap.get("data");
                contractNoIds.add(Util.null2String(result.get("contractNo")));
                fileNoIds.add(Util.null2String(result.get("fileNo")));
                fileName.add(fileInfo.getImagefilename());
            } catch (JsonProcessingException e) {
                toolUtil.writeErrorLog(e.toString());
                throw new RuntimeException("创建合同失败！");
            }
        }
//		创建合同文件成功之后收集合同编号，文件编号和合同文件的名字
        String joinContract = String.join(",", contractNoIds);
        String joinFileNoIds = String.join(",", fileNoIds);
        String joinFileName = String.join(",", fileName);
		/*
			TODO 主表创建字段 contract_no(合同编号)、file_no(文件编号)、file_name(文件名称)
			TODO 明细表添加字段，signed_status（合同方签署状态）
		 */
//		将合同的基本信息更新到流程主表中保存
        Map<String, Object> updateMap = ParaMap.create().put("contract_no", joinContract)
                .put("file_no", joinFileNoIds)
                .put("file_name", joinFileName);
        PrepSqlResultImpl sqlResult = Util.createSqlBuilder().updateSql(this.mainTableName, updateMap,
                Util.createPrepWhereImpl().whereAnd("id").whereEqual(mainMap.get("id")));
        toolUtil.writeDebuggerLog(sqlResult.getSqlStr() + "，参数：" + sqlResult.getArgs());
        rs.executeUpdate(sqlResult.getSqlStr(), sqlResult.getArgs());
//		将合同信息和流程表信息保存到自定义的建模表中
        updateMap.put("workflow_type", workflowId);
        updateMap.put("workflow_request_id", requestId);
        updateMap.put("workflow_main_table", mainTableName);
        updateMap.put("workflow_detail_table", tableName);
        updateMap.put("user_info", JSON.toJSONString(user));
//		1表示创建 2表示等待对方签署，3表示等待本方签署，4表示完成
        updateMap.put("contract_status", 1);
//		对方应该签署的数量
        updateMap.put("should_signed_num", detailMaps.size());
        updateMap.put("single_signed_num", 0);
//		现在已经签署的数量
        updateMap.put("signed_num", 0);
        updateMap.put("signed_type", 3);

        updateMap.put("main_id", String.valueOf(mainMap.get("id")));
        updateMap.put("queue_signed", "true".equals(queueSigned) ? 1 : 0);
        updateMap.put("single_contract_file_num", contractNoIds.size());
        //		如果需要控制签署规则
        if (faDaDaConfigDTO.getSignedType() == 1) {
//			需要控制签署规则
            if (Integer.parseInt(Util.null2String(mainMap.get(faDaDaConfigDTO.getFieldControl1()))) == faDaDaConfigDTO.getOnlyOwn()) {
//				只需要本方签署
                updateMap.put("contract_status", 3);
//		        对方应该签署的数量
                updateMap.put("should_signed_num", 0);
//		        现在已经签署的数量
                updateMap.put("signed_num", 0);
                updateMap.put("queue_signed", 0);
                updateMap.put("signed_type", 1);
            }
            if (Integer.parseInt(Util.null2String(mainMap.get(faDaDaConfigDTO.getFieldControl1()))) == faDaDaConfigDTO.getOnlyOther()) {
                updateMap.put("signed_type", 2);
            }
        }
//		查询合同信息中，是否存在该信息，如果存在着更新，不存在则插入
        String query = "select * from " + contractInfoTable + " where workflow_request_id = ?";
        rs.executeQuery(query, requestId);
        String formModeId = "52";
        if (rs.next()) {
            sqlResult = Util.createSqlBuilder().updateSql(contractInfoTable, updateMap,
                    Util.createPrepWhereImpl().whereAnd("workflow_request_id").whereEqual(requestId));
            toolUtil.writeDebuggerLog(sqlResult.getSqlStr() + "，参数：" + sqlResult.getArgs());
            rs.executeUpdate(sqlResult.getSqlStr(), sqlResult.getArgs());
//			权限重构
            ModeRightInfo mri = new ModeRightInfo();
            int dataId = rs.getInt("id");
            toolUtil.writeDebuggerLog("id：" + dataId);
            mri.rebuildModeDataShareByEdit(1, Util.getIntValue(formModeId, -1), dataId);
        } else {
            ModeDataIdUpdate mdu = ModeDataIdUpdate.getInstance();
            int dataId = mdu.getModeDataNewId(contractInfoTable,
                    Util.getIntValue(formModeId, -1),
                    1, 0, TimeUtil.getCurrentDateString(),
                    TimeUtil.getOnlyCurrentTimeString());
            sqlResult = Util.createSqlBuilder().updateSql(contractInfoTable, updateMap,
                    Util.createPrepWhereImpl().whereAnd("id").whereEqual(dataId));
            toolUtil.writeDebuggerLog(sqlResult.getSqlStr() + "，参数：" + sqlResult.getArgs());
            rs.executeUpdate(sqlResult.getSqlStr(), sqlResult.getArgs());
            ModeRightInfo mri = new ModeRightInfo();
            mri.rebuildModeDataShareByEdit(1, Util.getIntValue(formModeId, -1), dataId);
        }
    }

    /**
     * 处理合同创建数据
     *
     * @param contractField
     * @return
     */
    public List<FileInfo> contractHandle(String contractField) {
        String fileIds = Util.null2String(this.mainMap.get(contractField));
//		如果没有合同字段的数据，则返回一个空的
        if ("".equals(fileIds)) {
            return new ArrayList<>();
        }
        List<FileInfo> fileInfos = faDDContractMapping.queryImgFileIdByDocIds(fileIds);
        String customer = customerNo;
//		查询创建合同的企业编号
        if (StringUtils.isNullOrEmpty(customerNo)) {
            toolUtil.writeErrorLog("创建合同失败，失败原因：customerNo 为空！");
        }
//		处理数据信息
        for (FileInfo fileInfo : fileInfos) {
            InputStream inputStreamById = ImageFileManager.getInputStreamById(fileInfo.getImagefileid());
            fileInfo.setFile(inputStreamById);
            String imagefilename = fileInfo.getImagefilename();
            if (imagefilename == null) {
                return new ArrayList<>();
            }
            fileInfo.setContractExtension(imagefilename.substring(imagefilename.lastIndexOf(".")));
            fileInfo.setContractTitle(imagefilename);
            fileInfo.setCustomerNo(Util.null2String(customer));
            if (StringUtils.isNullOrEmpty(fileInfo.getCustomerNo())) {
                toolUtil.writeErrorLog("创建合同失败，失败原因，customer！");
//				fileInfo.setCustomerNo(Util.null2String(detail.get("companyno")));
            }
            fileInfo.setUploadType(1);
        }
        return fileInfos;
    }

    /**
     * 签署合同
     */
    public void signedContract(Map<String, Object> mainMap) {
//		获取配置表信息
        FaDaDaConfigDTO faDaDaConfigDTO = faDDContractMapping.queryConfig(workflowId, 3);
//      查询接口配置树形结构
        ApiConfigMainDTO apiConfigMainDTO = Util.queryApiConfigTree(faDaDaConfigDTO.getParamsConfig());
//		查询签署数据
        List<Map<String, Object>> dataArr = faDDContractService.getDataArr(requestId, workflowId, mainTableName, tableName);
//		处理数据
        List<Map<String, Object>> maps = faDDContractService.objectAndListHandle(apiConfigMainDTO.getDetails(), dataArr);
        if (maps == null) {
            toolUtil.writeErrorLog("签署合同错误，错误原因：maps为null!");
            throw new RuntimeException("签署合同错误，错误原因：maps为null！");
        }
        if (maps.size() == 0) {
            return;
        }
        RecordSet rs = new RecordSet();
        Map<String, Object> update = new HashMap<>();
//		顺序签署合同
        if ("true".equals(queueSigned)) {
            Map<String, Object> map = maps.get(0);
            if (faDaDaConfigDTO.getSignedType() == 1) {
//			需要控制签署规则
                if (Integer.parseInt(Util.null2String(mainMap.get(faDaDaConfigDTO.getFieldControl1()))) == faDaDaConfigDTO.getOnlyOther()) {
//				只需要对方签署
                    map.put("autoArchive", 1);
                }
//			双方签署
            }
            List<Map<String, Object>> requestList = signedRequest(map, apiConfigMainDTO);
            List<String> signedList = new ArrayList<>();
//            遍历将数据保存到合同信息表中
            for (Map<String, Object> result : requestList) {
                signedList.add(String.valueOf(result.get("signerUrl")));
            }
//			将合同签署地址保存到建模信息中
            update.put("contract_signed_url", String.join(" ; ", signedList));
            //			将合同签署信息更新到合同信息表中
            update.put("contract_status", 2);
//			update.put("single_signed_num",0);
            PrepSqlResultImpl sqlResult = Util.createSqlBuilder().updateSql(contractInfoTable, update,
                    Util.createPrepWhereImpl().whereAnd("workflow_request_id").whereEqual(requestId));
            rs.executeUpdate(sqlResult.getSqlStr(), sqlResult.getArgs());
            update.clear();
//			更新明细表合同信息  明细表添加字段，signed_status（合同方签署状态）
//			签署状态，1 已发送待签署，2 已签蜀
            update.put("signed_status", 1);
            sqlResult = Util.createSqlBuilder().updateSql(tableName, update,
                    Util.createPrepWhereImpl().whereAnd("id").whereEqual(String.valueOf(map.get("id"))));
            rs.executeUpdate(sqlResult.getSqlStr(), sqlResult.getArgs());
            return;
        }
//		不是顺序签署
        for (Map<String, Object> map : maps) {
            if (faDaDaConfigDTO.getSignedType() == 1) {
//			需要控制签署规则
                if (Integer.parseInt(Util.null2String(mainMap.get(faDaDaConfigDTO.getFieldControl1()))) == faDaDaConfigDTO.getOnlyOther()) {
//				只需要对方签署
                    map.put("autoArchive", 1);
                }
//			双方签署
            }
            signedRequest(map, apiConfigMainDTO);
//           TODO 一起签署不好控制催一催，没有一起签署的需求，暂且不做
        }
        //			将合同签署信息更新到合同信息表中
        update.put("contract_status", 2);
        PrepSqlResultImpl sqlResult = Util.createSqlBuilder().updateSql(contractInfoTable, update,
                Util.createPrepWhereImpl().whereAnd("workflow_request_id").whereEqual(requestId));
        rs.executeUpdate(sqlResult.getSqlStr(), sqlResult.getArgs());

    }

    /**
     * 合同签署发送请求
     *
     * @param map
     * @param apiConfigMainDTO
     */
    private List<Map<String, Object>> signedRequest(Map<String, Object> map, ApiConfigMainDTO apiConfigMainDTO) {
        String contractNos = Util.null2String(map.get("contractNo"));
        String[] split = contractNos.split(",");
        List<Map<String, Object>> list = new ArrayList<>();
//		RecordSet rs = new RecordSet();
        for (String s : split) {
            map.put("contractNo", s);
            ResponeVo responeVo = FaDDRequestUtils.signedContract(map, apiConfigMainDTO.getApiUrl());
            Map<String, Object> response = null;
            try {
                response = responeVo.getEntityMap();
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            if (!"200".equals(response.get("code"))) {
                toolUtil.writeErrorLog("法大大接口签署合同失败！");
                throw new RuntimeException("法大大接口签署合同失败!");
            }
            list.add((Map<String, Object>) response.get("data"));
        }
        return list;
    }


    @Override
    public String toString() {
        return "FaddContractUtil{" +
                "workflowId='" + workflowId + '\'' +
                ", requestId='" + requestId + '\'' +
                ", mainTableName='" + mainTableName + '\'' +
                ", tableName='" + tableName + '\'' +
                ", customerNo='" + customerNo + '\'' +
                ", contractField='" + contractField + '\'' +
                ", queueSigned='" + queueSigned + '\'' +
                ", contractInfoTable='" + contractInfoTable + '\'' +
                ", customerNoField='" + customerNoField + '\'' +
                ", detailMaps=" + detailMaps +
                ", mainMap=" + mainMap +
                '}';
    }

    public String getWorkflowId() {
        return workflowId;
    }

    public void setWorkflowId(String workflowId) {
        this.workflowId = workflowId;
    }

    public String getRequestId() {
        return requestId;
    }

    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }

    public String getMainTableName() {
        return mainTableName;
    }

    public void setMainTableName(String mainTableName) {
        this.mainTableName = mainTableName;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }


}
